﻿using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using OrganizedConfusion.Game_Objects;
using System.Threading;

namespace OrganizedConfusion
{
    public class LoadState : GameState
    {
        ObjectManager OM = ObjectManager.GetInstance();
        EventWaitHandle ExitThread = new ManualResetEvent(false);
        Thread LoadingThread;
        bool DoneLoading = false;
        float TimeElapsed = 0.0f;
        string file_to_load;

        public LoadState(string FileToLoad)
        {
            file_to_load = FileToLoad;
        }

        public override void LoadContent()
        {
            base.LoadContent();

            LoadingThread = new Thread(() => LoadFromBinary(file_to_load));
        }

        public override void Update(GameTime gameTime)
        {
            if (LoadingThread.ThreadState == ThreadState.Unstarted)
                LoadingThread.Start();
            TimeElapsed += (float)(gameTime.ElapsedGameTime.Milliseconds * 0.001f);

            lock (new object())
            {
                if (DoneLoading)
                {
                    ExitThread.Set();
                    //LoadingThread.Join();
                }

                if (!LoadingThread.IsAlive)
                    Statemanager.Changestate(new GamePlay());
            }
        }

        public override void Render(GameTime gameTime)
        {
            SpriteBatch spriteBatch = Statemanager.Spritebatch;
            Viewport viewport = Statemanager.GraphicsDevice.Viewport;

            Statemanager.GraphicsDevice.Clear(Color.Black);

            spriteBatch.Begin();
            spriteBatch.DrawString(Statemanager.Font, TimeElapsed.ToString() + " Seconds", new Vector2(viewport.Width * .5f, viewport.Height * .5f), Color.White);
            spriteBatch.End();
        }

        public bool LoadFromBinary(string file)
        {
            if (File.Exists(file))
            {
                BinaryReader bReader = new BinaryReader(File.Open(file, FileMode.Open, FileAccess.Read));

                try
                {
                    // If the file is not empty,
                    // read the application settings.
                    // First read 4 bytes into a buffer to
                    // determine if the file is empty.
                    byte[] testArray = new byte[3];
                    int count = bReader.Read(testArray, 0, 3);

                    // Reset the position in the stream to zero.
                    bReader.BaseStream.Seek(0, SeekOrigin.Begin);

                    ObjectFactory OF = new ObjectFactory();
                    int loopAmount = bReader.ReadInt32(); // #in list + player

                    for (int i = 0; i < loopAmount; i++)
                    {
                        int PosX, PosY, Type;

                        Type = bReader.ReadInt32();
                        PosX = bReader.ReadInt32();
                        PosY = bReader.ReadInt32();
                        switch ((BaseObject.OBJ_TYPE)Type)
                        {
                            case BaseObject.OBJ_TYPE.OBJ_BLOCK:
                                {
                                    OF.CreateBlock(new Vector2(PosX, PosY), "Textures/Block");
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_FLAG:
                                {
                                    OF.CreateCheckpoint(new Vector2(PosX, PosY), "Textures/Flag");
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_FLOOR:
                                {
                                    OF.CreateFloor(new Vector2(PosX, PosY), "Textures/Floor");
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_JUMPBOX:
                                {
                                    OF.CreateJumpBox(new Vector2(PosX, PosY), "Textures/background");
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_LAUNCHCANNON:
                                {
                                    bool facing = bReader.ReadBoolean();
                                    OF.CreateLaunchCannon(new Vector2(PosX, PosY), "Textures/background", facing);
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_PLAYER:
                                {
                                    OF.CreatePlayer(new Vector2(PosX, PosY), "Textures/DeN_Player", new Vector2());
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_RAMPS:
                                {
                                    bool facing = bReader.ReadBoolean();
                                    OF.CreateRamp(new Vector2(PosX, PosY), "Textures/Ramp", facing);
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_SPIKE:
                                {
                                    OF.CreateSpikes(new Vector2(PosX, PosY), "Textures/background");
                                    break;
                                }
                            case BaseObject.OBJ_TYPE.OBJ_TURRET:
                                {
                                    bool facing = bReader.ReadBoolean();
                                    OF.CreateTurret(new Vector2(PosX, PosY), "Textures/background", facing);
                                    break;
                                }
                        }
                    }
                }
                catch (EndOfStreamException e)
                {
                    Console.WriteLine("{0} caught and ignored. " +
                        "Using default values.", e.GetType().Name);
                }
                finally
                {
                    bReader.Close();
                }
                Console.Write("Success on binary load\n");
                DoneLoading = true;
                return true;
            }
            else
            {
                DoneLoading = false;
                return false;
            }
        }
    }
}
